<?php

/**
 * Maikuro CMS
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2010, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

final class AdministratorsViewController extends AbstractBackendEntityViewController
{
    /**
     *
     * @var AdministratorService
     */
    private $administratorService;

    /**
     *
     * @var PermissionService
     */
    private $permissionService;

    /**
     *
     * @var SiteService
     */
    private $siteService;

    /**
     *
     * @var string
     */
    protected $permissionSubject = 'administrator';

    /**
     *
     * @param BackendApplicationContext $applicationContext
     * @param AdministratorService $administratorService
     * @param PermissionService $permissionService
     * @param SiteService $siteService 
     */
    public function __construct(
            BackendApplicationContext $applicationContext,
            AdministratorService $administratorService,
            PermissionService $permissionService,
            SiteService $siteService) {
        $this->applicationContext = $applicationContext;
        $this->administratorService = $administratorService;
        $this->permissionService = $permissionService;
        $this->siteService = $siteService;

        $systemMenu = $this->applicationContext->getMenu()->getMenuItem('system');
        if ($systemMenu != null) {
            $administratorServiceMenu = $systemMenu->getSubMenu()->getMenuItem('administrators');
            if ($administratorServiceMenu != null) {
                $administratorServiceMenu->setActive();
            }
        }
    }

    /**
     * 
     */
    protected function handleCreateAction()
    {
        $this->request->forward('administrators/edit');
    }

    /**
     * 
     */
    protected function handleDeleteAction()
    {
        $this->applicationContext->checkPermission('administrator', Constants::ACCESS_LEVEL_VIEW_EDIT_CREATE_DELETE);

        $administratorId = (int) $this->request->getParam(1);

        $currentAdministrator = $this->administratorService->getAdministrator($administratorId);

        if ($currentAdministrator == null) {
            $this->request->redirectTo('404');
        }

        if ($this->request->isPost()) {
            if ($this->request->getPost('cancel')) {
                $this->request->redirectTo('administrators/');
            }
            try {
                $this->administratorService->delete($currentAdministrator);

                $this->administratorService->purgeCache();
                
                View::getMessenger()->addMessage('Administrator deleted.');
                $this->request->redirectTo('administrators/');
            } catch (Exception $e) {
                View::getMessenger()
                    ->addMessage('Administrator NOT deleted: ' . $e->getMessage(), Messenger::ERROR);
            }

        }

        $pageTitle = Translator::translate('Delete administrator') . " '$currentAdministrator->username'";
        $this->view->setVar('title', $pageTitle)
                   ->setName('administrators/delete')
                   ->render();
        
    }

    /**
     * 
     */
    protected function handleEditAction()
    {
        $this->applicationContext->checkPermission('administrator', Constants::ACCESS_LEVEL_VIEW_EDIT);

        if ($this->request->isPost() && $this->request->getPost('cancel')) {
            $this->request->redirectTo('administrators/');
        }

        $administratorId = (int) $this->request->getParam(1);

        $currentAdministrator = $this->administratorService->getAdministrator($administratorId);

        if ($currentAdministrator == null) {
            $this->applicationContext->checkPermission('administrator', Constants::ACCESS_LEVEL_VIEW_EDIT_CREATE);
            $currentAdministrator = $this->administratorService->create();
        }

        $currentAdministrator->password = null;

        $model = $this->prepareModel($currentAdministrator);

        $mb = new DefaultModelBinder();
        $mb->bindModel($model);

        if ($this->request->isPost()) {

            if ($model->administrator->id == null) {
                $existingAdministrator = $this->administratorService->getAdministratorByUsername($model->administrator->username);
                if ($existingAdministrator != null) {
                    $mb->getPropertyMetaData('administrator-username')
                       ->getValidationResult()
                       ->setValid(false)
                       ->addValidationMessage("There is already an existing administrator with that username.");
                }
                $existingAdministrator = $this->administratorService->getAdministratorByEmail($model->administrator->email);
                if ($existingAdministrator != null) {
                    $mb->getPropertyMetaData('administrator-email')
                       ->getValidationResult()
                       ->setValid(false)
                       ->addValidationMessage("There is already an existing administrator with that email.");
                }
            }

            if ($model->administrator->id == null && empty($model->administrator->password)) {
                $mb->getPropertyMetaData('administrator-password')
                   ->getValidationResult()
                   ->setValid(false)
                   ->addValidationMessage("The field 'Password' is required.");
            }
            
            if ($mb->isModelValid()) {
                try {
                    if ($currentAdministrator->id == null) {
                        $now = date("Y-m-d H:i:s");
                        $model->administrator->created = $now;
                        $model->administrator->password = hash('md5', $model->administrator->password . $now);
                    } else if (!empty($model->administrator->password)) {
                        $model->administrator->password = hash('md5', $model->administrator->password . $currentAdministrator->created);
                    }

                    $this->administratorService->save($model->administrator);
                    $this->administratorService->purgeCache();

                    if ($model->administrator->id == $this->applicationContext->getSessionUser()->getUserId()) {
                        $newSessionUser = new SessionUser($model->administrator->permissions, $model->administrator->id);
                        $this->applicationContext->setSessionUser($newSessionUser);
                    }

                    View::getMessenger()->addMessage('Administrator saved.');

                    $this->request->redirectTo('administrators');
        
                } catch (Exception $e) {
                    $errorMessage = Translator::translate('Could not save the administrator: ')
                                  . $e->getMessage();
                    View::getMessenger()->addMessage($errorMessage, Messenger::ERROR);
                }
            } else {
                View::getMessenger()->addMessage('Form not valid.', Messenger::ERROR);
            }
        }

        if ($currentAdministrator->id !== null) {
            $pageTitle = Translator::translate('Edit administrator') . " '$currentAdministrator->username'";
        } else {
            $pageTitle = Translator::translate('Create new administrator');
        }
        $this->view->setVar('title', $pageTitle)
                   ->setVar('model', $model)
                   ->setName('administrators/edit')
                   ->setLayout('system')
                   ->render();
    }

    private function prepareModel(AdministratorEntity $currentAdministrator)
    {
        $model = new AdministratorViewModel();
        $model->administrator = $currentAdministrator;

        $model->accessLevels = array(
            Constants::ACCESS_LEVEL_ACCESS_DENIED => Translator::translate('Access denied'),
            Constants::ACCESS_LEVEL_VIEW => Translator::translate('View'),
            Constants::ACCESS_LEVEL_VIEW_EDIT => Translator::translate('View and edit'),
            Constants::ACCESS_LEVEL_VIEW_EDIT_CREATE => Translator::translate('View, edit and create'),
            Constants::ACCESS_LEVEL_VIEW_EDIT_CREATE_DELETE => Translator::translate('View, edit, create and delete')
        );

        $model->sites = $this->siteService->getSites();
        $permissions = $this->permissionService->getPermissions();
        foreach ($permissions as $permission) {
            if ($permission->type == 'system') {
                $model->systemPermissions[] = $permission;
                if (!isset($currentAdministrator->permissions[$permission->subject])) {
                    $administratorPermission = $this->administratorService->createAdministratorPermission();
                    $administratorPermission->administratorId = $currentAdministrator->id;
                    $administratorPermission->permissionId = $permission->id;
                    $administratorPermission->accessLevel = Constants::ACCESS_LEVEL_ACCESS_DENIED;
                    $currentAdministrator->permissions[$permission->subject] = $administratorPermission;
                }
            } else {
                foreach ($model->sites as $site) {
                    $accessKey = $site->id . '/' . $permission->subject;
                    if (!isset($currentAdministrator->permissions[$accessKey])) {
                        $administratorPermission = $this->administratorService->createAdministratorPermission();
                        $administratorPermission->administratorId = $currentAdministrator->id;
                        $administratorPermission->permissionId = $permission->id;
                        $administratorPermission->siteId = $site->id;
                        $administratorPermission->accessLevel = Constants::ACCESS_LEVEL_ACCESS_DENIED;
                        $currentAdministrator->permissions[$accessKey] = $administratorPermission;
                    }
                }

                $model->sitePermissions[] = $permission;
            }
        }
        return $model;
    }

    /**
     *
     */
    protected function handleListAction() 
    {
        $this->applicationContext->checkPermission('administrator', Constants::ACCESS_LEVEL_VIEW);

        $pageTitle = Translator::translate('Administrators');
        $this->view
             ->setVar('title', $pageTitle)
             ->setVar('administrators', $this->administratorService->getAdministrators())
             ->setLayout('system')
             ->render();

    }
}